package cn.wolfcode.p2p.business.service.impl;

import cn.wolfcode.p2p.base.domain.Account;
import cn.wolfcode.p2p.base.exception.DisplayableException;
import cn.wolfcode.p2p.base.qo.TransferCreditQueryObject;
import cn.wolfcode.p2p.base.service.IAccountService;
import cn.wolfcode.p2p.base.util.Constants;
import cn.wolfcode.p2p.base.util.UserContext;
import cn.wolfcode.p2p.business.domain.BidRequest;
import cn.wolfcode.p2p.business.domain.CreditTransfer;
import cn.wolfcode.p2p.business.mapper.CreditTransferMapper;
import cn.wolfcode.p2p.business.service.IAccountFlowService;
import cn.wolfcode.p2p.business.service.IBidRequestService;
import cn.wolfcode.p2p.business.service.ICreditTransferService;
import cn.wolfcode.p2p.business.service.IPaymentScheduleDetailService;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.Date;
import java.util.List;

@Service@Transactional
public class CreditTransferServiceImpl implements ICreditTransferService {
    @Autowired
    private CreditTransferMapper creditTransferMapper;
    @Autowired
    private IBidRequestService bidRequestService;
    @Autowired
    private IAccountService accountService;
    @Autowired
    private IAccountFlowService accountFlowService;
    @Autowired
    private IPaymentScheduleDetailService paymentScheduleDetailService;

    @Override
    public int save(CreditTransfer creditTransfer) {
        return creditTransferMapper.insert(creditTransfer);
    }

    @Override
    public int update(CreditTransfer creditTransfer) {
        int count = creditTransferMapper.updateByPrimaryKey(creditTransfer);
        if (count == 0){
            System.out.println("乐观锁异常:creditTransferId:"+ creditTransfer);
            throw new DisplayableException("系统繁忙,请稍后再试");
        }
        return count;
    }

    @Override
    public CreditTransfer get(Long id) {
        return creditTransferMapper.selectByPrimaryKey(id);
    }

    @Override
    public PageInfo listCanTransferCredit(TransferCreditQueryObject qo) {
        PageHelper.startPage(qo.getPageNum(), qo.getPageSize());
        List result = creditTransferMapper.listCanTransferCredit(UserContext.getCurrent().getId());
        return new PageInfo(result);
    }

    @Override
    public void creditTransfer(Long[] bidId) {
        if (bidId != null) {
            List<CreditTransfer> readyForCredit = creditTransferMapper.listReadyToTransferCredit(UserContext.getCurrent().getId(), bidId);
            for (CreditTransfer ct : readyForCredit) {
                ct.setBidRequestState(Constants.BIDREQUEST_STATE_BIDDING);
                ct.setTransFrom(UserContext.getCurrent());
                ct.setPublishDate(new Date());
                creditTransferMapper.insert(ct);
                creditTransferMapper.changePaymentScheduleDetailIntransState(ct.getBidId(), Constants.IN_TRANS);
            }
        }
    }

    @Override
    public PageInfo queryPage(TransferCreditQueryObject qo) {
        PageHelper.startPage(qo.getPageNum(), qo.getPageSize());
        List result = creditTransferMapper.queryData(qo);
        return new PageInfo(result);
    }

    @Override
    public void subscribe(Long id) {
        //1.根据id获取当前债权标对象
        CreditTransfer ct = this.get(id);
        BidRequest oldBidRequest = bidRequestService.get(ct.getBidRequestId());
        Account subscribeAccount = accountService.get(UserContext.getCurrent().getId());


        //判断是否不为空,标的状态是否是在招标中
        if (ct != null && ct.getBidRequestState() == Constants.BIDREQUEST_STATE_BIDDING){
            //2.判断当前登录用户既不是原来的借款人,也不是发布债权标用户,账户可用金额>=债权标的认购本金
            if (!UserContext.getCurrent().getId().equals(oldBidRequest.getCreateUser().getId())
                    && !UserContext.getCurrent().getId().equals(ct.getTransFrom().getId())
                    && subscribeAccount.getUsableAmount().compareTo(ct.getBidRequestAmount())>=0
                    ){
                //3.执行认购,设置相关属性
                ct.setTransTo(UserContext.getCurrent());
                ct.setTransDate(new Date());
                ct.setBidRequestState(Constants.BIDREQUEST_STATE_COMPLETE_PAY_BACK);
                this.update(ct);
                //4.认购人
                //可用金额减少,待收本金,待收利息增加,生成认购成功流水
                subscribeAccount.setUsableAmount(subscribeAccount.getUsableAmount().subtract(ct.getBidRequestAmount()));
                subscribeAccount.setUnReceivePrincipal(subscribeAccount.getUnReceivePrincipal().add(ct.getBidRequestAmount()));
                subscribeAccount.setUnReceiveInterest(subscribeAccount.getUnReceiveInterest().add(ct.getRemainInterest()));
                accountFlowService.createSubscribeFlow(subscribeAccount,ct.getBidRequestAmount());
                accountService.update(subscribeAccount); //不要忘记更新
                //5.发标人
                //可用金额增加,待收本金,待收利息减少,生成转让成功的流水
                Account transAccount = accountService.get(ct.getTransFrom().getId());
                transAccount.setUsableAmount(transAccount.getUsableAmount().add(ct.getBidRequestAmount()));
                transAccount.setUnReceivePrincipal(transAccount.getUnReceivePrincipal().subtract(ct.getBidRequestAmount()));
                transAccount.setUnReceiveInterest(transAccount.getUnReceiveInterest().subtract(ct.getRemainInterest()));
                accountFlowService.createTransSuccessFlow(transAccount,ct.getBidRequestAmount());
                accountService.update(transAccount);
                //6.其他
                //还款明细中的投资人id变化
                creditTransferMapper.changePaymentScheduleDetailInvestorId(ct.getBidId(), UserContext.getCurrent().getId());
                //还款明细中的intrans变成不是债权转让状态
                creditTransferMapper.changePaymentScheduleDetailIntransState(ct.getBidId(), Constants.NO_IN_TRANS);
            }
        }
    }

    @Override
    public CreditTransfer findNeedCancel(Long bidId) {
        return creditTransferMapper.findNeedCancel(bidId);
    }

    @Override
    public void cancel(CreditTransfer needCancel) {
        needCancel.setBidRequestState(Constants.BIDREQUEST_STATE_UNDO);
        this.update(needCancel);
        creditTransferMapper.changePaymentScheduleDetailIntransState(needCancel.getBidId(),Constants.NO_IN_TRANS);
    }
}
